package com.crawler.util.template;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

/**
 * Created by guor on 2015/6/12.
 */
public class URLTemplateBuilder {

    public static final String PATH_SEP = "/";

    /**
     * 构造模式串，规则： 1. 以/分割 2. 参数串全部删除，即？后面 3. 纯数字段用*替换 4. 数字+字母组合用*替换
     * <p>
     * 如：http://legal.firefox.news.cn/15/0612/10/C3X7FA9OHNGUTY21.html
     * 模式串为：http://legal.firefox.news.cn/[*]/[*]/[*]/[*].html
     *
     * @param str
     * @return
     */
    public static URLTemplate build(String str) {
        if (str == null || str.isEmpty() || str.indexOf("http") == -1) {
            return null;
        }
        URL url = null;
        try {
            url = new URL(str);
        } catch (MalformedURLException e) {
            System.out.println(e.getMessage());
            return null;
        }
        String host = url.getHost();// 域名
        URLTemplate t = new URLTemplate(host);

        String path = url.getPath();
        if (path == null || path.isEmpty() || path.equals(PATH_SEP)) {
            return t;
        }
        if (path.charAt(0) == '/') {
            path = path.substring(1);
        }
        String[] ss = path.split(PATH_SEP);
        if (ss.length <= 0) {
            return t;
        }

        List<String> paths = new LinkedList<String>();
        for (int i = 0; i < ss.length - 1; i++) {
            paths.add(generatePattern(ss[i]));
        }
        String lastSep = ss[ss.length - 1];
        int ch = lastSep.indexOf('.');
        if (ch != -1) {
            String p = lastSep.substring(0, ch);
            paths.add(generatePattern(p));
            t.setDoctype(lastSep.substring(ch + 1));
        } else {
            paths.add(generatePattern(lastSep));
        }
        t.setPaths(paths);
        return t;
    }

    /**
     * 用模式串，编译/构建一个StringTemplate对象，不作任何转义
     * 所谓模式串，所有格式如下：legal.firefox.news.cn/[d]/[d]/[d]/[*].html
     *
     * @param pattern
     * @return
     */
    public static URLTemplate compile(String pattern) {
        Objects.requireNonNull(pattern);
        String[] path = pattern.split(PATH_SEP);
        String host = path[0];
        URLTemplate template = new URLTemplate(host);
        List<String> paths = new LinkedList<String>();
        for (int i = 1; i < path.length; i++) {
            if (i != path.length - 1) {
                paths.add(path[i]);
                continue;
            }
            int ch = path[i].indexOf('.');
            if (ch != -1) {
                String p = path[i].substring(0, ch);
                paths.add(p);
                template.setDoctype(path[i].substring(ch + 1));
            } else {
                paths.add(path[i]);
            }
        }
        template.setPaths(paths);
        return template;
    }

    public static final String generatePattern(String path) {
        return generatePattern(path, true);
    }

    /**
     * 123456 --> [d]
     * <p>
     * 123456-1234 --> [d]-[d]
     * <p>
     * 123456_1234 --> [d]_[d]
     *
     * @return
     */
    public static final String generatePattern(String path, boolean ignore) {
        if (isDigitalString(path)) {
            return URLTemplate.PATTERN_DIGITAL;
        }

        StringBuilder buf = new StringBuilder();
        int mch = path.indexOf('-');
        if (mch != -1) {
            String[] ss = path.split("-");
            int i = 0;
            for (; i < ss.length - 1; i++) {
                buf.append(generatePattern(ss[i], true)).append("-");
            }
            buf.append(generatePattern(ss[i], true));
            return buf.toString();
        }

        int ch = path.indexOf('_');
        if (ch != -1) {
            String[] ss = path.split("_");
            int i = 0;
            for (; i < ss.length - 1; i++) {
                buf.append(generatePattern(ss[i], true)).append("_");
            }
            buf.append(generatePattern(ss[i], true));
            return buf.toString();
        }
        if (ignore && containsDigitalString(path)) {
            return URLTemplate.PATTERN_ALL;
        }
        return path;
    }

    public static final boolean containsDigitalString(String s) {
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (Character.isDigit(ch)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否纯数字串
     */
    public static final boolean isDigitalString(String s) {
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (!Character.isDigit(ch)) {
                return false;
            }
        }
        return true;
    }

    public static final boolean isSpaceChar(char ch) {
        return Character.isSpaceChar(ch) || Character.isWhitespace(ch);
    }

    public static final boolean isLineChar(char ch) {
        return ch == '-' || ch == '_';
    }
}
